/////////////////////////////////////////////////////////////////////////
//
// Amuse Engine SDK - graphics/shaders
// Copyright( c) 2015.  All Rights Reserved
//
// File:		AECompiledShaderPass.h
// Author:		Gianluca Belardelli
// Date:		02/07/2015
//
/////////////////////////////////////////////////////////////////////////
#ifndef _AECOMPILEDSHADERPASS_H_
#define _AECOMPILEDSHADERPASS_H_

class AECompiledShaderPass : public AEReferencedObject
{
// Members
private:
	AEShaderModel m_eShaderModel[ AESHADERSTAGE_MAXPLATFORMSTAGE ];
	AEUINT32 m_uiStreamMask;
	AEShaderProgramHandle m_uiProgramHandle;

public:
	AEVertexShaderObjectPtr		m_spVertexShader;
	AEPixelShaderObjectPtr		m_spPixelShader;
	AEGeometryShaderObjectPtr	m_spGeometryShader;

	AEBOOL32 m_bModified;	 ///< Set this to true when modifying a shader pass. This will indicate to the engine that the shader will have to be set again even if it is already active.

// Methods
private:
	// Function to create a program handle (if required).
	void _createProgramHandle( void );
	void _destroyProgramHandle( void );

public:
	/** @name Costruttore / Distruttore */
	/// @{
	/// \brief
	///   Constructor; Sets defaults
	AE_DLLIMPEXP AECompiledShaderPass( void );

	/// \brief
	///   Destructor
	AE_DLLIMPEXP virtual ~AECompiledShaderPass( void );

	/// @}
	/** @name Accessing Constant Buffers */
	/// @{
	/// \brief
	///   Accesses one of the shader-specific constant buffers
	/// The passed buffer index can either be VSS_VertexShader, VSS_PixelShader, 
	/// VSS_GeometryShader (DX10, DX11) or VSS_HullShader/VSS_DomainShader/VSS_ComputeShader (DX11).
	/// The returned buffer provides a range of shader registers that are used by this shader
	/// instance.
	/// The buffer object can be used to modify registers in the buffer. The constants are uploaded to the
	/// graphics card at shader bind time.
	/// However, only constants inside the valid range are supported. For instance, if a shader uses
	/// vertex shader registers c65-c80, only these constants can be modified in the vertex shader
	/// constant buffer.
	/// \param Stage
	///   The following constants are currently supported:
	///   \li VSS_VertexShader : access the vertex shader constant table
	///   \li VSS_PixelShader : access the pixel shader constant table
	///   \li VSS_GeometryShader : access the geometry shader constant table (DX10/11 only)
	///   \li VSS_HullShader : access the hull shader constant table (DX11 only)
	///   \li VSS_DomainShader : access the domain shader constant table (DX11 only)
	///   \li VSS_ComputeShader : access the compute shader constant table (DX11 only)
	/// \return
	///   VShaderConstantBuffer* pBuffer: A contant buffer that provides the range of constants used
	///   by this shader
	/// \sa VShaderConstantBuffer
	AE_DLLIMPEXP AEShaderConstantBuffer *GetConstantBuffer( AEShaderStage eStage );

	/// \brief
	///   Helper function to get the texture sampler index associated with the passed sampler name
	/// 
	/// The name has to match a sampler name that is used in the vertex/pixel shader. If no sampler with the specified name exists in this shader,
	/// this function returns -1.
	/// 
	/// The index can be used for a sampler lookup in the shader's m_pStateGroupSamplers and m_pStateGroupTextures
	/// arrays.
	/// 
	/// To look up a sampler index independently for vertex-, geometry- or pixel shader, you can use
	/// VCompiledShaderPass::GetConstantBuffer(VSS_VertexShader)->GetSamplerIndexByName(szSamplerName)
	/// instead.
	///
	/// \param Stage
	///   The shader stage in which to query the sampler name.
	/// 
	/// \param szSamplerName
	///   Name of the sampler to find. The comparison is case-insensitive.
	/// 
	/// \return
	///   int iSamplerIndex: index of the sampler (or -1)
	AE_DLLIMPEXP AEINT32 GetSamplerIndexByName( AEShaderStage eStage, const char *lpSamplerName ) const;

	/// @}
	/** @name Overridables */
	/// @{
	/// \brief
	///   Virtual overridable that is called for every parameter in the parameter string that
	///   modifies this shader
	/// The default implementation of this function maps the parameter to both vertex and pixel
	/// shader constant table. 
	/// Custom implementations can use this function to map a parameter to any custom member, such as
	/// light source keys etc.
	/// \param szVarname
	///   The name of the parameter, e.g. "LightColor"
	/// \param szValueStr
	///   The value string. Vector components are separated by ','. The default implementation parses
	///   this string and maps it to the constant buffer.
	/// \return
	///   bool bResult: true if updating this parameter was successful
	/// \sa VFloatConstantBuffer
	/// \sa VFloatConstantBuffer::GetRegisterByName
	AE_DLLIMPEXP virtual AEBOOL32 UpdateShaderParam( const char *lpVarname, const char *lpValueStr );
	/// @}
	/** @name Operatori */
	/// @{
	/// \brief
	///   Assignment operator; copies data from the passed compiled shader pass
	AE_DLLIMPEXP AECompiledShaderPass &operator = ( const AECompiledShaderPass &refOther );

	/// \brief
	///   Comparison operator. Not virtual. Thus for custom comparison functions use the IsEqual
	///   function
	AE_DLLIMPEXP bool operator == ( const AECompiledShaderPass &refOther ) const;

	/// \brief
	///   Comparison operator. Not virtual. Thus for custom comparison functions use the IsEqual
	///   function
	AE_DLLIMPEXP AEBOOL32 operator != ( const AECompiledShaderPass &refOther ) const;

	/// \brief
	///   Creates a clone of this shader pass instance
	/// 
	/// The base implementation creates a class instance of the same type using the type manager.
	/// Then it copies all states of the VCompiledShaderPass class.
	/// 
	/// Custom shader classes can override this function to copy their own relevant members
	/// 
	/// \return
	///   VCompiledShaderPass *pNewInstance: A new shader instance of the same class as this
	AE_DLLIMPEXP virtual AECompiledShaderPass *Clone( void ) const;

	/// \brief
	///   Overridable to compare two shader instances
	/// 
	/// The base implementation of this function calls the '==' operator that in turn compares the
	/// class types and the base members.
	/// 
	/// Custom shader classes can override this function to compare their own relevant members
	/// 
	/// \param other
	///   Other instance to compare
	/// 
	/// \return
	///   bool bEqual: Comparison result
	AE_DLLIMPEXP virtual AEBOOL32 IsEqual( const AECompiledShaderPass &refOther ) const {return (*this) == refOther;}
	/// @}

	/** @name Internal Functions */
	/// @{
	/// \brief
	///   Clears all shader programs previously copied by CopyShadersFromResource().
	///
	/// \sa CopyShadersFromResource
	///
	AE_DLLIMPEXP void ClearShaderPrograms( void );

	/// \brief
	///   Checks if the shader program configuration is valid for this shader pass.
	///
	/// This function will return false after calling ClearShaders(). 
	///
	/// \sa ClearShaderPrograms CopyShadersFromResource
	///
	AE_DLLIMPEXP AEBOOL32 AreShaderProgramsValid( void ) const;

	AE_DLLIMPEXP const void *GetShader( AEShaderStage eShader );

	AE_FORCEINLINE AEShaderModel GetShaderModel( AEShaderStage eShader ) const;

	/// \brief Returns the vertex-stream mask.
	AE_FORCEINLINE AEUINT32 GetStreamMask( void ) const;

	AE_FORCEINLINE AEShaderProgramHandle GetProgramHandle( void ) const;

	AE_DLLIMPEXP AEUINT32 LinkProgram( void );
};

typedef AESmartPtr<AECompiledShaderPass>	AECompiledShaderPassPtr;

#include "AECompiledShaderPass.inl"

#endif // _AECOMPILEDSHADERPASS_H_

